import {
	TASK_KEY_LABEL_MAP,
	SSL_CATEGORY_KEY_LABEL_MAP,
	ASSET_TYPE_MAP,
} from '../../../common/constants';
import errorCodesBuilder from '../../helpers/errorCodesBuilder';
import warningCounts from '../../helpers/warningCounts';

const errorCodes = errorCodesBuilder('修改任务告警修改状态失败');

const titleBuilder = taskType => {
	if (taskType === 'securityEvent') {
		return '处理';
	} else if (taskType === 'asset') {
		return '确认';
	}
	return '修复';
};

const detailBuilder = ({ task, warnArr, titleText, isResolved, note = '' }) => {
	switch (task.taskType) {
		case 'vul':
			return `更新资产地址${task.target}的${
				TASK_KEY_LABEL_MAP[task.taskType]
			}“${warnArr.map(x => x.title).join('、')}”状态为${
				isResolved ? `已${titleText}` : `未${titleText}`
			}。`;
		case 'ssl':
			return `更新资产地址${task.target}的${
				TASK_KEY_LABEL_MAP[task.taskType]
			}“${warnArr
				.map(x => `${SSL_CATEGORY_KEY_LABEL_MAP[x.category]}：${x.title}`)
				.join('、')}”状态为${
				isResolved ? `已${titleText}` : `未${titleText}`
			}。`;
		case 'securityEvent':
			return `更新资产地址${task.target}的风险URL${warnArr.map(
				x => x.affects
			)}状态为${isResolved ? `已${titleText}` : `未${titleText}`}`;
		case 'asset':
			return `将资产变动中资产名称为${note}的${warnArr
				.map(w => `${ASSET_TYPE_MAP[w.category]}`)
				.join('、')}更新为${
				isResolved ? `已${titleText}` : `未${titleText}`
			}。`;
		default:
			return '';
	}
};
export default {
	description: '修改任务告警修改状态',
	type: 'Task',
	args: {
		isResolved: 'Boolean!',
		taskId: 'MongoID!',
		warnIds: '[String]!',
	},
	resolve: async (root, { isResolved, taskId, warnIds }, { request }) => {
		const {
			server: {
				app: {
					model: { Task, Job, Asset },
				},
			},
			auth: {
				credentials: { uid, permissionMap },
			},
		} = request;

		let task;
		let ref;
		try {
			const query = { _id: taskId };
			if (!permissionMap[`cloud-monitor\x01editTask\x010`]) {
				query.uid = uid;
			}
			task = await Task.findOne(query);
			ref = await (task.taskType === 'asset' ? Asset : Job).findOne({
				_id: task.refId,
			});
		} catch (err) {
			const error = errorCodes['[01][修改告警状态]查找任务mongo记录失败'].from(
				err
			);
			request.log.error({ error }, error.rawMessage);
			throw error;
		}

		if (!task) {
			const error = errorCodes['[01][修改告警状态]没有找到对应mongo记录'];
			request.log.error({ taskId, warnIds }, error.internalMessage);
			throw error;
		}

		const warnIdMap = warnIds.reduce((obj, x) => {
			obj[x] = true;
			return obj;
		}, {});

		const warnArr = [];
		const warnings = task.result.warnings.map(x => {
			if (warnIdMap[x.id]) {
				warnArr.push(x);
				x.isResolved = isResolved;
				x.ignoredTime = null;
				ref.ignoredWarnIdMap = {
					...ref.ignoredWarnIdMap,
					[x.id]: null,
				};
			}
			return x;
		});
		Object.assign(task.result, warningCounts(warnings));
		task.result.warnings = warnings;
		if (task.result.warnings.every(x => x.ignoredTime || x.isResolved)) {
			// 所有异常都解决或忽略
			task.securityStatus = 'safe';
		} else {
			task.securityStatus = 'warning';
		}

		try {
			task.refId = ref._id;
			await Promise.all([task.save(), ref.save()]);
		} catch (err) {
			const error = errorCodes['[01][修改告警状态]更新mongo记录失败'].from(err);
			request.log.error({ error }, error.rawMessage);
			throw error;
		}

		const titleText = titleBuilder(task.taskType);
		const job = await Job.findById(task.jobId);

		request.log.audit(
			{
				affects: [task.target],
				module: 'task',
				actionType: 'update',
				actionMessage: `更新${
					task.taskType === 'securityEvent'
						? '风险'
						: task.taskType === 'asset'
						? '资产'
						: '漏洞'
				}状态`,
				detail: detailBuilder({
					task,
					warnArr,
					titleText,
					isResolved,
					note: job.note,
				}),
			},
			`[${task.target}]修改告警为${
				isResolved ? `已${titleText}` : `未${titleText}`
			}`
		);

		return task;
	},
};
